home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume17 / news_split1.6 / part01 next >
Encoding:
Internet Message Format  |  1991-02-18  |  16.3 KB

  1. From: fmc@cnam.cnam.fr (Frederic Chauveau)
  2. Newsgroups: comp.sources.misc
  3. Subject: v17i001:  news_split1.6 - News to Archive, Part01/01
  4. Message-ID: <1991Feb18.223025.5242@sparky.IMD.Sterling.COM>
  5. Date: 18 Feb 91 22:30:25 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 81cb8f8a a8758f38 736d574a 408f1b7f
  8.  
  9. Submitted-by: Frederic Chauveau <fmc@cnam.cnam.fr>
  10. Posting-number: Volume 17, Issue 1
  11. Archive-name: news_split1.6/part01
  12.  
  13. This is version 1.6 of news_split.  news_split is used to create and 
  14. update an archive tree from the *.sources.* usenet groups. 
  15.  
  16. Frederic
  17. ----
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then feed it
  20. # into a shell via "sh file" or similar.  To overwrite existing files,
  21. # type "sh file -c".
  22. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  23. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  24. # If this archive is complete, you will see the following message at the end:
  25. #        "End of archive 1 (of 1)."
  26. # Contents:  README INSTALL Makefile news_split.c
  27. # Wrapped by kent@sparky on Mon Feb 18 16:23:01 1991
  28. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  29. if test -f 'README' -a "${1}" != "-c" ; then 
  30.   echo shar: Will not clobber existing file \"'README'\"
  31. else
  32. echo shar: Extracting \"'README'\" \(2932 characters\)
  33. sed "s/^X//" >'README' <<'END_OF_FILE'
  34. X/*
  35. X * news_split        [fmc] 09/02/91        Version 1.6
  36. X *            Browse a given NewsGroup (usualy comp.sources.???
  37. X *            and try to update/maintain a directory for the
  38. X *            sources found in it. 
  39. X *            I use it to maintain the ~ftp/pub/comp.sources.???
  40. X *            from the equivalent News directories.
  41. X *
  42. X *    CopyLeft and CopyWrong Frederic Chauveau [fmc@cnam.cnam.fr]
  43. X */
  44. X
  45. XUsage: news_split [-s|-n] [-l logdir] [-f groupfile | group1 ... groupN]
  46. X
  47. XThe group_name is in Usenet format (eg. comp.sources.games). A file with
  48. Xthe same name is created, containing the Min and Max article number already
  49. Xprocessed. 
  50. X
  51. XA log file is created for each group processed. This logfile can be used to
  52. Xmaintain an index of the created files. These logfile are created in the 
  53. XLOGDIR directory (same as the destination directory by default). You can
  54. Xspecify another directory with the '-l' option.
  55. X
  56. XIf the '-s' flag is present, new files will supercede old files in case of
  57. Xconflicting names. This is the default.
  58. X
  59. XIf the '-n' flag is present, new files will not supercede old files.
  60. X
  61. XGroup names are apecified either on the command line, or with the 
  62. X'-f groupfile' option. In the last case, groupfile is a list of group names,
  63. Xone per line.
  64. X
  65. XYou can merge group_name and options on the command line.
  66. X
  67. X
  68. XKnown Bugs/Limitations. 
  69. X
  70. XIt works on Ultrix 4.0 and later. The main system dependencies should
  71. Xbe the scandir function. I've provided a replacement but it has not been
  72. Xchecked. 
  73. X
  74. XThe header format is the most limitating factor. We're looking for :
  75. X
  76. Xa Subject line ("^Subject:") 
  77. Xa Posting-number line ("^Posting-number:") and
  78. Xa Archive-name line ("^Archive-name:").
  79. X
  80. Xin the first 30 lines, or before the first line beginning with a '#',
  81. Xwhichever happend first.
  82. X
  83. XFrom the Subject line we get a first subject as the word following Subject:
  84. XFrom the Post line we get a Volume-number and perhaps an Issue number.
  85. XFrom the Arch line (if present) we get a destination filename.
  86. X
  87. XThe destination file will be :
  88. X
  89. X  if No Posting-number line, we copy the file as the article number. 
  90. X
  91. X  if No Archive-name line, and Posting-number isn't recognized as an
  92. X     Information posting, we copy the file under the subject name (i.e.
  93. X     vxxxcnnn usualy.)
  94. X
  95. X  if We have a volume number VV (from the Posting-number line) and an issue
  96. X     number, we save as FTP_DIR/group_name/volumeVV/filename, where
  97. X     filename comes from the archive-name line.
  98. X
  99. X  if we have a volume number VV (from the Posting-number line) and an info
  100. X     number NN (From the Posting-number line) we save as
  101. X     FTP_DIR/group_name/volumeVV/InfoNN.
  102. X
  103. XElse we warn that we couldn't parse the Posting-number line.
  104. X
  105. XMy current use for it is to run it once a day on the following groups :
  106. X
  107. Xcomp.sources.amiga    comp.sources.apple2    comp.sources.atari
  108. Xcomp.sources.games    comp.sources.mac    comp.sources.misc
  109. Xcomp.sources.sun    comp.sources.unix    comp.sources.x
  110. Xcomp.binaries.amiga    comp.binaries.atari    comp.binaries.ibm.pc
  111. X
  112. END_OF_FILE
  113. if test 2932 -ne `wc -c <'README'`; then
  114.     echo shar: \"'README'\" unpacked with wrong size!
  115. fi
  116. # end of 'README'
  117. fi
  118. if test -f 'INSTALL' -a "${1}" != "-c" ; then 
  119.   echo shar: Will not clobber existing file \"'INSTALL'\"
  120. else
  121. echo shar: Extracting \"'INSTALL'\" \(1931 characters\)
  122. sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
  123. Xnews_split Version 1.6        Bugs, Gripes, etc... to fmc@cnam.cnam.fr
  124. X                Last Modification:    12 Feb 91
  125. X
  126. XBefore compiling, check to see if the default values for the following
  127. Xdefines are adequates :
  128. X
  129. X- NEWS_SPOOL    (/usr/spool/news)
  130. X  The root directory of the news tree. news_split will try to find
  131. X  articles in this tree.
  132. X
  133. X- FTP_DIR    (/local/ftp/pub)
  134. X  The root directory where the destination files will be created. I
  135. X  use it to update an anonymous ftp server.
  136. X
  137. X- LOGFILE    (%s/Index.ns)
  138. X  A format string for printf.
  139. X- LOGDIR    (FTP_DIR)
  140. X  the root directory for logfiles.
  141. X  A log file for comp.sources.misc will be created as :
  142. X    LOGDIR/comp.sources.misc/Index.ns
  143. X
  144. X
  145. XCompilation options and caveats :
  146. X
  147. X- For systems without /usr/include/unistd.h, add -DNOUNISTD to CFLAGS.
  148. X  It will include <sys/files.h> instead. Only purpose is to get
  149. X  defines for access() return codes.
  150. X
  151. X- For systems without the scandir() function, add -DNOSCANDIR to CFLAGS.
  152. X  A scandir replacement is provided, but hasn't been extensively
  153. X  tested. Purpose is to fill an array with 'interesting' file names.
  154. X
  155. X- Some systems have no DIRENT variable type (usually defined in
  156. X  <sys/dir.h>). In most case, it is similar to 'struct direct'. I
  157. X  think you need the BSD-style directory functionalities.
  158. X
  159. X
  160. X
  161. XFor news_split to work, you need read_access to your NEWS_SPOOL
  162. Xdirectory (usualy the case) and write_access to FTP_DIR and LOGDIR
  163. Xdirectories. 
  164. X
  165. X
  166. XIf you encounter troubles with news_split, don't sue me, warn me :-)
  167. X
  168. X
  169. X                            [fmc]
  170. X
  171. X-------------------------------------------------------------------------------
  172. XFrederic Chauveau             Conservatoire National des Arts et Metiers
  173. Xfmc@cnam.cnam.fr
  174. X-------------------------------------------------------------------------------
  175. XParadise is exactly like where you are right now, only much, much better.
  176. X                               William S. Burroughs
  177. X-------------------------------------------------------------------------------
  178. X
  179. X
  180. X
  181. END_OF_FILE
  182. if test 1931 -ne `wc -c <'INSTALL'`; then
  183.     echo shar: \"'INSTALL'\" unpacked with wrong size!
  184. fi
  185. # end of 'INSTALL'
  186. fi
  187. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  188.   echo shar: Will not clobber existing file \"'Makefile'\"
  189. else
  190. echo shar: Extracting \"'Makefile'\" \(539 characters\)
  191. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  192. XALLFILES = news_split.c Makefile README INSTALL
  193. X
  194. X# for system with no scandir function add -DNOSCANDIR to CFLAGS
  195. X# for system with no <unistd.h> file, add -dNOUNISTD  to CFLAGS
  196. X
  197. XCFLAGS = -O
  198. X
  199. X# Perhaps you need to add -ldir to LDFLAGS.
  200. X
  201. XLDFLAGS =
  202. X
  203. XDESTDIR = /usr/local/bin
  204. XINSTALL = install -c
  205. X
  206. Xnews_split : news_split.o
  207. X    $(CC) $(CFLAGS) news_split.o -o news_split $(LDFLAGS)
  208. X
  209. Xclean :
  210. X    rm -f news_split *.o *~ core
  211. X
  212. Xinstall : news_split
  213. X    $(INSTALL) news_split $(DESTDIR)
  214. X
  215. Xshar :
  216. X    shar -n news_split -a -x -c  -o news_split.shar $(ALLFILES)
  217. END_OF_FILE
  218. if test 539 -ne `wc -c <'Makefile'`; then
  219.     echo shar: \"'Makefile'\" unpacked with wrong size!
  220. fi
  221. # end of 'Makefile'
  222. fi
  223. if test -f 'news_split.c' -a "${1}" != "-c" ; then 
  224.   echo shar: Will not clobber existing file \"'news_split.c'\"
  225. else
  226. echo shar: Extracting \"'news_split.c'\" \(7587 characters\)
  227. sed "s/^X//" >'news_split.c' <<'END_OF_FILE'
  228. X/*
  229. X * news_split        [fmc] 09/02/91        Version 1.6
  230. X *            Browse a given NewsGroup (usualy comp.sources.???
  231. X *            and try to update/maintain a directory for the
  232. X *            sources found in it. 
  233. X *            I use it to maintain the ~ftp/pub/comp.sources.???
  234. X *            from the equivalent News directories.
  235. X *
  236. X *            Usage: news_split [-sn] [-l logdir] group ... group
  237. X *                or news_split [-sn] [-l logdir] -f groupfile
  238. X *
  239. X *            In the second case, groupfile is a file containing 
  240. X *            each group to be processed, one per line.
  241. X *
  242. X *    CopyLeft and CopyWrong Frederic Chauveau [fmc@cnam.cnam.fr]
  243. X */
  244. X
  245. X#include <stdio.h>
  246. X#ifdef NOUNISTD
  247. X#include <sys/file.h>
  248. X#else
  249. X#include <unistd.h>
  250. X#endif
  251. X#include <ctype.h>
  252. X#include <errno.h>
  253. X#include <sys/types.h>
  254. X#include <sys/dir.h>
  255. X
  256. X
  257. X#ifndef NEWS_SPOOL
  258. X#define NEWS_SPOOL "/usr/spool/news"
  259. X#endif /* no NEWS_SPOOL */
  260. X
  261. X#ifndef FTP_DIR
  262. X#define FTP_DIR "/local/ftp/pub"
  263. X#endif /* no FTP_DIR */
  264. X
  265. X#ifndef LOGFILE
  266. X#define LOGFILE "%s/Index.ns"
  267. X#endif /* no LOGFILE */
  268. X
  269. X#ifndef LOGDIR
  270. X#define LOGDIR FTP_DIR
  271. X#endif
  272. X
  273. XFILE *logfile;
  274. Xchar *logdir = LOGDIR;
  275. X
  276. Xchar logname[BUFSIZ];
  277. Xchar Supercede_P = 1;
  278. X
  279. X#ifndef DIRENT
  280. X#define DIRENT struct direct
  281. X#endif
  282. X
  283. X#ifdef NOSCANDIR
  284. X
  285. Xint scandir(DirName,NameList,Select,Sort)
  286. Xchar *DirName;
  287. XDIRENT *(*NameList[]);
  288. Xint (*Select)(), (*Sort)(); {
  289. X  int c = 0;
  290. X  DIRENT **tab, *entry;
  291. X  DIR *dirp;
  292. X
  293. X  dirp = opendir(DirName);
  294. X  while (entry = readdir(dirp))
  295. X    c += (Select ? (*Select)(entry) : 1);
  296. X  tab = (DIRENT **) malloc(c * sizeof(DIRENT *));
  297. X  rewinddir(dirp); c = 0;
  298. X  while (entry = readdir(dirp))
  299. X    if (!Select || (*Select)(entry))
  300. X      tab[c++] = entry;
  301. X  if (Sort)
  302. X    qsort(tab,c,sizeof(DIRENT *),Sort);
  303. X  *NameList = tab;
  304. X  return c;
  305. X}
  306. X
  307. X#endif /* NOSCANDIR */  
  308. X
  309. XDirSelect(dp)
  310. XDIRENT *dp; {
  311. X  return isdigit(dp->d_name[0]);
  312. X}
  313. X
  314. Xvoid CreateDirAndFile(dirname,infile)
  315. Xchar *dirname;
  316. XFILE *infile; {
  317. X  FILE *outfile;
  318. X  char *p = dirname;
  319. X  char buf[BUFSIZ];
  320. X
  321. X  while (p = (char *) strchr(p+1,'/'))
  322. X    {
  323. X      *p = '\0';
  324. X      if (mkdir(dirname,0766) && (errno != EEXIST))
  325. X    {
  326. X      FILE *foo = stderr;
  327. X      *stderr = *logfile;
  328. X      perror(dirname);
  329. X      *stderr = *foo;
  330. X      perror(dirname);
  331. X      return;
  332. X    }
  333. X      *p = '/';
  334. X    }
  335. X  if (!infile)
  336. X    return;
  337. X  if (access(dirname,F_OK) != -1)
  338. X    {
  339. X      fprintf(stderr,"  Warning: %s %s\n",
  340. X          (Supercede_P ? "Superceding" : "Not Superceding"),dirname);
  341. X      fprintf(logfile,"  Warning: %s %s\n",
  342. X          (Supercede_P ? "Superceding" : "Not Superceding"),dirname);
  343. X      if (!Supercede_P)
  344. X    return;
  345. X    }
  346. X  outfile = fopen(dirname,"w");
  347. X  if (!outfile)
  348. X    {
  349. X      FILE *foo = stderr;
  350. X      *stderr = *logfile;
  351. X      perror(dirname);
  352. X      *stderr = *foo;
  353. X      perror(dirname);
  354. X    }
  355. X  else
  356. X    {
  357. X      rewind(infile);
  358. X      while (fgets(buf,BUFSIZ,infile))
  359. X    fputs(buf,outfile);
  360. X      fclose(outfile);
  361. X    }
  362. X}  
  363. X
  364. Xvoid SaveIt(pnumb,aname,subj,anumb,infile,group)
  365. Xchar *pnumb, *aname, *group, *subj, *anumb;
  366. XFILE *infile; {
  367. X  int vol, iss;
  368. X  char dirname[BUFSIZ];
  369. X
  370. X  pnumb[strlen(pnumb)-1] = '\0';
  371. X  if (sscanf(pnumb,"Posting-number: Volume %d, Info%*[^0-9] %d",&vol,&iss) != 2)
  372. X    {
  373. X      if (sscanf(pnumb,"Posting-number: Volume %d %*[^0-9] %d",&vol,&iss) != 2)
  374. X    {
  375. X      fprintf(stderr," Couldn't get volume for article [%s]\n",anumb);
  376. X      fprintf(logfile," Couldn't get volume for article [%s]\n",anumb);
  377. X      sprintf(dirname,"%s/%s/%s",FTP_DIR,group,anumb);
  378. X      CreateDirAndFile(dirname,infile);
  379. X    }
  380. X    }
  381. X  else
  382. X      sprintf(aname,"Archive-name: Info%d\n",iss);
  383. X  if (!aname[0])
  384. X    {
  385. X      sprintf(dirname,"%s/%s/%s",FTP_DIR,group,subj);
  386. X      CreateDirAndFile(dirname,infile);
  387. X    }
  388. X  else
  389. X    {
  390. X      aname += 14; aname[strlen(aname)-1] = '\0';
  391. X      sprintf(dirname,"%s/%s/volume%d/%s",FTP_DIR,group,vol,aname);
  392. X      fprintf(logfile,"Volume %3d, Issue %3d :\t\t%s\n",vol,iss,aname);
  393. X      CreateDirAndFile(dirname,infile);
  394. X    }
  395. X}
  396. X
  397. Xvoid ProcArticle(art,group)
  398. Xchar *art, *group; {
  399. X  FILE *inp;
  400. X  char buf[BUFSIZ], postnum[BUFSIZ], archnam[BUFSIZ];
  401. X  char subject[BUFSIZ];
  402. X  int i = 0;
  403. X
  404. X  if (!(inp = fopen(art,"r")))
  405. X    {
  406. X      perror(art);
  407. X      return;
  408. X    }
  409. X  *postnum = *archnam = *subject = '\0';
  410. X  while (fgets(buf,BUFSIZ,inp))
  411. X    {
  412. X      if ((*postnum && *archnam && *subject) ||
  413. X      (*buf == '#') || (i > 30))
  414. X    {
  415. X      SaveIt(postnum,archnam,subject,art,inp,group);
  416. X      break;
  417. X    }
  418. X      if (!strncmp("Subject:",buf,8)) 
  419. X    sscanf(buf,"Subject: %[^ :]",subject);
  420. X      else if (!strncmp("Posting-number",buf,14))
  421. X    strcpy(postnum,buf);
  422. X      else if (!strncmp("Archive-name",buf,12))
  423. X    strcpy(archnam,buf);
  424. X      i++;
  425. X    }
  426. X  fclose(inp);
  427. X}
  428. X
  429. XGroupToDir(group,dirname)
  430. Xchar *group, *dirname; {
  431. X  char *p;
  432. X  strcpy(dirname,group);
  433. X  
  434. X  for (p = (char *) strchr(dirname,'.'); p; p = (char *) strchr(p,'.'))
  435. X    *p++ = '/';
  436. X}
  437. X
  438. Xvoid ProcGroup(group,first,last)
  439. Xint *first, *last;
  440. Xchar *group; {
  441. X  register int i, art_num, max, nf = *first, nl = *last;
  442. X  char dirname[BUFSIZ];
  443. X  DIRENT **namelist;
  444. X
  445. X  chdir(NEWS_SPOOL);
  446. X  GroupToDir(group,dirname);
  447. X  chdir(dirname);
  448. X  max = scandir(".",&namelist,DirSelect,NULL);
  449. X  if (max == -1)
  450. X    {
  451. X      perror(dirname);
  452. X      fprintf(stderr,"Cannot scan %s/%s\n",NEWS_SPOOL,group);
  453. X      return;
  454. X    }
  455. X  for (i = 0; i < max; i++)
  456. X    {
  457. X      art_num = atoi(namelist[i]->d_name);
  458. X      if (art_num < *first)
  459. X    ProcArticle(namelist[i]->d_name,group);
  460. X      else if (art_num > *last)
  461. X    ProcArticle(namelist[i]->d_name,group);
  462. X      if (art_num && art_num < nf)
  463. X    nf = art_num;
  464. X      if (art_num && art_num > nl)
  465. X    nl = art_num;
  466. X    }
  467. X  *first = nf;
  468. X  *last = nl;
  469. X}
  470. X
  471. XFILE *OpenLog(group_name)
  472. Xchar *group_name; {
  473. X  char tmp[BUFSIZ], ln[BUFSIZ];
  474. X  FILE *logfile;
  475. X
  476. X  sprintf(tmp,LOGFILE,group_name);
  477. X  sprintf(ln,"%s/%s",logdir,tmp);
  478. X  CreateDirAndFile(ln,NULL);
  479. X  if (!(logfile = fopen(ln,"w")))
  480. X    {
  481. X      perror(ln);
  482. X      logfile = stderr;
  483. X    }
  484. X  return logfile;
  485. X}
  486. X
  487. Xvoid ProcName(group_name, backtodir)
  488. Xchar *group_name, *backtodir; {
  489. X  FILE *tmp;
  490. X  int first, last;
  491. X  long now;
  492. X
  493. X  now = time((long *) 0);
  494. X  logfile = OpenLog(group_name);
  495. X  tmp = fopen(group_name,"r");
  496. X  if (!tmp)
  497. X    {
  498. X      first = 9999;
  499. X      last = 0;
  500. X    }
  501. X  else
  502. X    {
  503. X      fscanf(tmp,"%d %d",&first,&last);
  504. X      fclose(tmp);
  505. X    }
  506. X  fprintf(logfile," -- Processing group %s (%d %d) at %s",group_name,first,
  507. X      last,ctime(&now));
  508. X  fprintf(stderr,"Processing group %s (%d %d)\n",group_name,first,last);
  509. X  ProcGroup(group_name,&first,&last);
  510. X  chdir(backtodir);
  511. X  tmp = fopen(group_name,"w");
  512. X  fprintf(tmp,"%d %d\n",first,last);
  513. X  fclose(tmp);
  514. X  if (logfile != stderr)
  515. X    fclose(logfile);
  516. X  fprintf(stderr,"Processed  group %s (%d %d)\n",group_name,first,last);
  517. X}
  518. X
  519. X
  520. Xvoid Usage(s,pn)
  521. Xchar *s, *pn; {
  522. X  fprintf(stderr,"Unknown option %s\n",s);
  523. X  fprintf(stderr,"Usage: %s [-sn] [-l logdir] [-f group_file | group1 .. groupn]\n",pn);
  524. X  exit(1);
  525. X}
  526. X
  527. Xmain(argc,argv)
  528. Xchar **argv; {
  529. X  FILE *from_file;
  530. X  char cwd[BUFSIZ], *pname = *argv;
  531. X  
  532. X  getcwd(cwd,BUFSIZ);
  533. X  while (++argv, --argc)
  534. X    {
  535. X      if (**argv == '-')
  536. X    {
  537. X      switch (argv[0][1])
  538. X        {
  539. X        case 's' : case 'S' : Supercede_P = 1; break;
  540. X        case 'n' : case 'N' : Supercede_P = 0; break;
  541. X        case 'l' : case 'L' : logdir = argv[1]; argv++; argc--; break;
  542. X        case 'f' : case 'F' : 
  543. X          from_file = fopen(argv[1],"r"); 
  544. X          if (!from_file)
  545. X        {
  546. X          perror(argv[1]);
  547. X          argv++; argc--; 
  548. X        }
  549. X          break;
  550. X        default: Usage(*argv,pname);
  551. X        }
  552. X      continue;
  553. X    }
  554. X      if (from_file)
  555. X    {
  556. X      char gname[BUFSIZ];
  557. X
  558. X      while (fgets(gname,BUFSIZ,from_file))
  559. X        {
  560. X          gname[strlen(gname)-1] = '\0';
  561. X          ProcName(gname,cwd);
  562. X        }
  563. X      fclose(from_file);
  564. X      from_file = NULL;
  565. X    }
  566. X      else 
  567. X    ProcName(*argv,cwd);
  568. X    }
  569. X}
  570. X
  571. X      
  572. END_OF_FILE
  573. if test 7587 -ne `wc -c <'news_split.c'`; then
  574.     echo shar: \"'news_split.c'\" unpacked with wrong size!
  575. fi
  576. # end of 'news_split.c'
  577. fi
  578. echo shar: End of archive 1 \(of 1\).
  579. cp /dev/null ark1isdone
  580. MISSING=""
  581. for I in 1 ; do
  582.     if test ! -f ark${I}isdone ; then
  583.     MISSING="${MISSING} ${I}"
  584.     fi
  585. done
  586. if test "${MISSING}" = "" ; then
  587.     echo You have the archive.
  588.     rm -f ark[1-9]isdone
  589. else
  590.     echo You still need to unpack the following archives:
  591.     echo "        " ${MISSING}
  592. fi
  593. ##  End of shell archive.
  594. exit 0
  595. exit 0 # Just in case...
  596. -- 
  597. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  598. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  599. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  600. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  601.